using Cairo;
using Gtk;

namespace Ribbons {

	public class ApplicationButton : BaseButton {

		private const double LINE_WIDTH = 1.0;

		/** Fired when the button is clicked. */
		public signal void clicked ();

		public ApplicationMenu menu {
			get { return _app_menu; }
		}

		private ApplicationMenu _app_menu;

		public ApplicationButton () {
			set_flags (get_flags () | WidgetFlags.NO_WINDOW);

			add_events (Gdk.EventMask.BUTTON_PRESS_MASK
			          | Gdk.EventMask.BUTTON_RELEASE_MASK
			          | Gdk.EventMask.POINTER_MOTION_MASK);

			_app_menu = new ApplicationMenu (this);

			this.height_request = 36;
			this.width_request = 36;

			_enabled = true;
		}

		// XXX-GEETK: workaround
		private bool has_click_listener () {
			var signal_id = Signal.lookup ("clicked",
			                               typeof (ApplicationButton));
			return Signal.has_handler_pending (this, signal_id, 0, true);
		}

		/** Fires the click event. */
		public void click () {
			if (_enabled && has_click_listener ()) {
				clicked ();
			}

			_app_menu.realize.connect (() => {
				int x, y;
				get_parent_window ().get_origin (out x, out y);
				x += this.allocation.x;
				y += Gdk.Rect.bottom ((Gdk.Rectangle) this.allocation);
				_app_menu.window.move (x, y);
			});

			_app_menu.show ();
		}

		internal override bool bound_widget_button_press_event (
		                                                  Widget sender,
		                                                  Gdk.EventButton evnt)
		{
			button_press_event (evnt);
			return false;
		}

		internal override bool bound_widget_button_release_event (
		                                                  Widget sender,
		                                                  Gdk.EventButton evnt)
		{
			button_release_event (evnt);
			click ();
			return false;
		}

		internal override bool expose_event (Gdk.EventExpose event) {
			var cr = Gdk.cairo_create (this.window);

			cr.rectangle (event.area.x, event.area.y,
			              event.area.width, event.area.height);
			cr.clip ();
			draw (cr);

//			cr.target.dispose ();		// XXX-GEETK
//			cr.dispose ();

			return base.expose_event (event);
		}

		private void draw (Context cr) {
			_theme.draw_application_button (cr, (Gdk.Rectangle) this.allocation,
			                                _state, LINE_WIDTH, this);
		}

		internal override bool button_press_event (Gdk.EventButton event) {
//			bool ret = base.button_press_event (event);		// XXX-GEETK
			bool ret = false;
			_state = Theme.ButtonState.PRESSED;
			if (!_enabled) {
				_state = Theme.ButtonState.DEFAULT;
			}
			queue_draw ();
			click ();
			return ret;
		}

		internal override bool button_release_event (Gdk.EventButton event) {
//			bool ret = base.button_release_event (event);	// XXX-GEETK
			bool ret = false;
			_state = Theme.ButtonState.HOVER;
			if (!_enabled) {
				_state = Theme.ButtonState.DEFAULT;
			}
			queue_draw ();
			return ret;
		}

		internal override bool enter_notify_event (Gdk.EventCrossing event) {
//			bool ret = base.enter_notify_event (event);		// XXX-GEETK
			bool ret = false;
			_state = Theme.ButtonState.HOVER;
			if (!_enabled) {
				_state = Theme.ButtonState.DEFAULT;
			}
			queue_draw ();
			return ret;
		}

		internal override bool leave_notify_event (Gdk.EventCrossing event) {
//			bool ret = base.leave_notify_event (event);		// XXX-GEETK
			bool ret = false;
			_state = Theme.ButtonState.DEFAULT;
			queue_draw ();
			return ret;
		}
	}
}

